package vn.edu.saigontech.ncms.model.result;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity
@DiscriminatorValue("final_test")
@SuppressWarnings("serial")
public class FinalTest extends AbstractTest {

	public static final double WRITTEN_WEIGHT = 0.4;
	public static final double ORAL_WEIGHT = 0.2;

	@Column(name = "make_up")
	private Boolean makeUp;

	@OneToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "make_up_test_id")
	private MakeUpTest makeUpTest;

	/**
	 * get the grade detail from the offering class
	 * 
	 * @return
	 */
	private GradeDetail getGradeDetail() {
		return this.getOfferingMember().getReceipt().getOffering()
				.getFinalGradeDetail();
	}

	/**
	 * compute the written score
	 * 
	 * @return
	 */
	public Double getWrittenScore() {
		try {
			GradeDetail gradeDetail = this.getGradeDetail();
			double totalWritten = gradeDetail.computeTotalWritternScore(this);
			if ((totalWritten % 0.5) == 0)
				return totalWritten;
			return (double) Math.round(totalWritten);
		} catch (Exception ex) {
		}
		return null;
	}

	public Double getConvertedWrittenScore() {
		Double total = this.getWrittenScore();
		if (total == null)
			return null;
		return total * WRITTEN_WEIGHT;
	}

	public Double getOralScore() {
		try {
			if ((this.speaking % 0.5) == 0)
				return this.speaking;
			return (double) Math.round(this.speaking);
		} catch (Exception ex) {
		}
		return null;
	}

	public Double getConvertedOralScore() {
		Double total = this.getOralScore();
		if (total == null)
			return null;
		return total * ORAL_WEIGHT;
	}

	public Double getTotal() {
		if (this.getConvertedWrittenScore() != null &&
				this.getConvertedOralScore() != null)
			return this.getConvertedWrittenScore() + this.getConvertedOralScore();
		return null;
	}

	@Deprecated
	public boolean oldPassed() {
		Grade grade = this.getOldGrade();
		return grade != null && !Grade.F.equals(grade);
	}

	@Deprecated
	public Grade getOldGrade() {
		Double total = this.getOldTotal();
		if (total == null)
			return null;
		if (total >= 90 && total <= 100) {
			return Grade.A;
		} else if (total >= 80 && total < 90) {
			return Grade.B;
		} else if (total >= 70 && total < 80) {
			return Grade.C;
		} else if (total >= 60 && total < 70) {
			return Grade.D;
		} else if (total >= 0 && total < 60) {
			return Grade.F;
		}
		return null;
	}

	@Deprecated
	public Double getOldTotal() {
		try {
			double total = this.listening + this.speaking + this.reading
					+ this.writing;
			if ((total % 0.5) == 0)
				return total;
			return (double) Math.round(total);
		} catch (Exception ex) {
		}
		return null;
	}

	/**
	 * check whether all grade has been input
	 */
	public boolean isAllGradeInput() {
		return this.getGradeDetail().isAllGradeInput(this);
	}

	/**
	 * check whether there is any grade has been input from the test
	 * 
	 * @return
	 */
	public boolean isAnyGradeInput() {
		return this.getGradeDetail().isAnyGradeInput(this);
	}

	// to check whether this final test is make-up
	public boolean checkIsMakeUp() {
		if (this.makeUp != null)
			return this.makeUp;
		return false;
	}

	/**
	 * Getter Setter
	 */

	public Boolean getMakeUp() {
		return makeUp;
	}

	public void setMakeUp(Boolean makeUp) {
		this.makeUp = makeUp;
	}

	public MakeUpTest getMakeUpTest() {
		return makeUpTest;
	}

	public void setMakeUpTest(MakeUpTest makeUpTest) {
		this.makeUpTest = makeUpTest;
	}
}